import {
  Controller,
  Post,
  Body,
  Get,
  Param,
  UseGuards,
  HttpException,
  HttpStatus,
  HttpCode,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from '../../../../../modules/user/jwt/jwt-auth.guard';
import { CurrentUser } from 'src/decorators/current.user';
import { UserEntity } from 'src/types/modules/user/entities/user.entity';
import { CurrentRole } from '@/decorators/current.role';
import { ClientRole } from '@/modules/user/role/role.type';
import { VFSService } from './vfs.service';
import { FileWriteResult, WriteOptions } from './type';
import { getCurrentProject, getTypeByParams } from '@/utils/editor-adapter/editorResource';
import {
  InitializeFileSystemDto,
  FileSystemFile,
  ApiResponse,
  InitializationResult,
} from './dto/vfs.dto';
import { IPublicTypeRootSchema } from '@alilc/lowcode-types';
import { ITypeEntity } from '@/types/modules/superType/types';

@ApiTags('VFS - Virtual File System')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('editor/vfs')
export class VFSController {
  constructor(private readonly vfsService: VFSService) {}

  /**
   * 初始化项目文件系统
   * 当编辑器打开项目时调用此接口
   */
  @Post('initialize/:projectId')
  @HttpCode(HttpStatus.OK)
  async initializeProject(
    @Param('projectId') projectId: string,
    @Body() body: InitializeFileSystemDto,
  ): Promise<ApiResponse<InitializationResult>> {
    try {
      console.log(`收到初始化请求: ${projectId}`);

      if (!projectId || !body.project) {
        return {
          success: false,
          message: '参数错误',
          error: 'projectId 和 project 都是必需的',
        };
      }

      // 执行文件系统初始化
      const result = await this.vfsService.initializeFileSystem(projectId, body.project);

      return {
        success: result.success,
        message: result.success ? '文件系统初始化成功' : '文件系统初始化失败',
        data: result,
      };
    } catch (error) {
      console.error('初始化失败', error.stack);
      return {
        success: false,
        message: '服务器错误',
        error: error.message,
      };
    }
  }

  /**
   * 初始化项目文件系统
   * 当编辑器打开项目时调用此接口
   */
  @Post('update-project-hashs/:projectId')
  @HttpCode(HttpStatus.OK)
  async updateProjectHashes(@Param('projectId') projectId?: string): Promise<any> {
    try {
      console.log(`收到初始化请求: ${projectId}`);

      // 执行文件系统初始化
      const result = await this.vfsService.updateProjectHashes(projectId || undefined);
      try {
        await this.vfsService.updateDocumentsHashes(projectId);
      } catch (e) {
        console.error(e);
      }
      try {
        await this.vfsService.updateITypeEntityHashes(projectId);
      } catch (e) {
        console.error(e);
      }

      return result;
    } catch (error) {
      console.error('初始化失败', error.stack);
      return {
        success: false,
        message: '服务器错误',
        error: error.message,
      };
    }
  }

  /**
   * 初始化项目文件系统
   * 当编辑器打开项目时调用此接口
   */
  @Post('update-document-hashs/:projectId')
  @HttpCode(HttpStatus.OK)
  async updateDocumentsHashes(@Param('projectId') projectId: string): Promise<any> {
    try {
      console.log(`收到初始化请求: ${projectId}`);

      // 执行文件系统初始化
      const result = await this.vfsService.updateDocumentsHashes(projectId);

      return result;
    } catch (error) {
      console.error('初始化失败', error.stack);
      return {
        success: false,
        message: '服务器错误',
        error: error.message,
      };
    }
  }

  /**
   * 初始化项目文件系统
   * 当编辑器打开项目时调用此接口
   */
  @Post('update-type-hashs/:projectId')
  @HttpCode(HttpStatus.OK)
  async updateTypeHashes(@Param('projectId') projectId: string): Promise<any> {
    try {
      console.log(`收到初始化请求: ${projectId}`);

      // 执行文件系统初始化
      const result = await this.vfsService.updateITypeEntityHashes(projectId);

      return result;
    } catch (error) {
      console.error('初始化失败', error.stack);
      return {
        success: false,
        message: '服务器错误',
        error: error.message,
      };
    }
  }

  @ApiOperation({ summary: '读取文件内容' })
  @Post('read')
  async readFile(
    @Body()
    body: {
      projectId: string;
      path: string;
      documentSchema?: IPublicTypeRootSchema;
      typeEntity?: ITypeEntity;
      returnSource?: boolean;
    },
    @CurrentUser() user: UserEntity,
    @CurrentRole() role: ClientRole,
  ) {
    try {
      const { projectId, path, documentSchema, typeEntity, returnSource } = body;

      // 验证权限
      const hasPermission = await this.vfsService.checkPermission(user.id, projectId, path, 'read');

      if (!hasPermission) {
        throw new HttpException('您没有权限读取此文件', HttpStatus.FORBIDDEN);
      }

      const data = await this.vfsService.readFile(projectId, path, {
        documentSchema,
        typeEntity,
        returnSource,
      });

      return {
        success: true,
        data,
      };
    } catch (error) {
      throw new HttpException(
        error.message || '读取文件失败',
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @ApiOperation({ summary: '写入文件内容' })
  @Post('write')
  async writeFile(
    @Body()
    body: {
      projectId: string;
      path: string;
      content: string;
      options?: WriteOptions;
    },
    @CurrentUser() user: UserEntity,
    @CurrentRole() role: ClientRole,
  ): Promise<{ success: boolean; data: FileWriteResult; }> {
    try {
      const { projectId, path, content, options = {} } = body;

      // 验证权限
      const hasPermission = await this.vfsService.checkPermission(
        user.id,
        projectId,
        path,
        'write',
      );

      if (!hasPermission) {
        throw new HttpException('您没有权限写入此文件', HttpStatus.FORBIDDEN);
      }

      // 文件校验
      // if (!options.skipValidation) {
      // const validationResult = await this.validateFileX(path, content);
      // if (!validationResult.isValid) {
      //   throw new HttpException(
      //     `文件校验失败: ${validationResult.errors.join(', ')}`,
      //     HttpStatus.BAD_REQUEST,
      //   );
      //   }
      // }

      const result = await this.vfsService.writeFile(projectId, path, content, {
        documentSchema: options.documentSchema,
        writeMode: options.writeMode,
        author: options.author,
        message: options.message,
        skipValidation: options.skipValidation,
        preview: options.preview,
        returnSource: options.returnSource,
        user,
        userId: user.id,
        teamId: role.teamId,
      });

      return {
        success: true,
        data: result,
      };
    } catch (error) {
      throw new HttpException(
        error.message || '写入文件失败',
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @ApiOperation({ summary: '批量读取文件' })
  @Post('batchRead')
  async batchReadFiles(
    @Body()
    body: {
      projectId: string;
      paths: string[];
    },
    @CurrentUser() user: UserEntity,
    @CurrentRole() role: ClientRole,
  ) {
    try {
      const { projectId, paths } = body;

      const results = await Promise.all(
        paths.map(async (path) => {
          try {
            const hasPermission = await this.vfsService.checkPermission(
              user.id,
              projectId,
              path,
              'read',
            );

            if (!hasPermission) {
              return {
                path,
                success: false,
                error: '没有读取权限',
              };
            }

            const content = await this.vfsService.readFile(projectId, path, {});

            return {
              path,
              success: true,
              content,
            };
          } catch (error) {
            return {
              path,
              success: false,
              error: error.message,
            };
          }
        }),
      );

      return {
        success: true,
        data: {
          results,
          total: paths.length,
          successCount: results.filter((r) => r.success).length,
          timestamp: Date.now(),
        },
      };
    } catch (error) {
      throw new HttpException(
        error.message || '批量读取文件失败',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @ApiOperation({ summary: '批量写入文件' })
  @Post('batchWrite')
  async batchWriteFiles(
    @Body()
    body: {
      projectId: string;
      files: Array<{
        path: string;
        content: string;
      }>;
      options?: {
        skipValidation?: boolean;
        writeMode?: 'code' | 'vi';
        author?: string;
        message?: string;
      };
    },
    @CurrentUser() user: UserEntity,
    @CurrentRole() role: ClientRole,
  ) {
    try {
      const { projectId, files, options = {} } = body;

      const results = await Promise.all(
        files.map(async (file) => {
          try {
            const hasPermission = await this.vfsService.checkPermission(
              user.id,
              projectId,
              file.path,
              'write',
            );

            if (!hasPermission) {
              return {
                path: file.path,
                success: false,
                error: '没有写入权限',
              };
            }

            // 文件校验
            if (!options.skipValidation) {
              const validationResult = await this.validateFileX(file.path, file.content);
              if (!validationResult.isValid) {
                return {
                  path: file.path,
                  success: false,
                  error: `文件校验失败: ${validationResult.errors.join(', ')}`,
                };
              }
            }

            const result = await this.vfsService.writeFile(projectId, file.path, file.content, {
              writeMode: options.writeMode || 'code',
              author: options.author || user.name,
              message: options.message || 'Batch update via VFS',
              userId: user.id,
            });

            return {
              path: file.path,
              success: true,
              hash: result.hash,
              isNewFile: result.isNewFile,
              isChanged: result.isChanged,
            };
          } catch (error) {
            return {
              path: file.path,
              success: false,
              error: error.message,
            };
          }
        }),
      );

      return {
        success: true,
        data: {
          results,
          total: files.length,
          successCount: results.filter((r) => r.success).length,
          timestamp: Date.now(),
        },
      };
    } catch (error) {
      throw new HttpException(
        error.message || '批量写入文件失败',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @ApiOperation({ summary: '删除文件' })
  @Post('delete')
  async deleteFile(
    @Body() body: { projectId: string; path: string },
    @CurrentUser() user: UserEntity,
    @CurrentRole() role: ClientRole,
  ) {
    try {
      const { projectId, path } = body;

      const hasPermission = await this.vfsService.checkPermission(
        user.id,
        projectId,
        path,
        'delete',
      );

      if (!hasPermission) {
        throw new HttpException('您没有权限删除此文件', HttpStatus.FORBIDDEN);
      }

      await this.vfsService.deleteFile(projectId, path, user.id);

      return {
        success: true,
        data: {
          path,
          timestamp: Date.now(),
        },
      };
    } catch (error) {
      throw new HttpException(
        error.message || '删除文件失败',
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @ApiOperation({ summary: '列出目录内容' })
  @Post('readdir')
  async readdir(
    @Body()
    body: {
      projectId: string;
      path: string;
      options?: {
        recursive?: boolean;
        includeTypeEntity?: boolean;
      };
    },
    @CurrentUser() user: UserEntity,
    @CurrentRole() role: ClientRole,
  ) {
    try {
      const { projectId, path, options = {} } = body;

      const hasPermission = await this.vfsService.checkPermission(user.id, projectId, path, 'read');

      if (!hasPermission) {
        throw new HttpException('您没有权限读取此目录', HttpStatus.FORBIDDEN);
      }

      const entries = await this.vfsService.readdir(projectId, path, options);

      return {
        success: true,
        data: {
          path,
          entries,
          timestamp: Date.now(),
        },
      };
    } catch (error) {
      throw new HttpException(
        error.message || '读取目录失败',
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @ApiOperation({ summary: '文件校验' })
  @Post('validate')
  async validateFile(
    @Body()
    body: {
      projectId: string;
      path: string;
      content: string;
    },
    @CurrentUser() user: UserEntity,
    @CurrentRole() role: ClientRole,
  ) {
    try {
      const { projectId, path, content } = body;

      const hasPermission = await this.vfsService.checkPermission(user.id, projectId, path, 'read');

      if (!hasPermission) {
        throw new HttpException('您没有权限访问此文件', HttpStatus.FORBIDDEN);
      }

      const validationResult = await this.validateFileX(path, content);

      return {
        success: true,
        data: {
          path,
          ...validationResult,
          timestamp: Date.now(),
        },
      };
    } catch (error) {
      throw new HttpException(error.message || '文件校验失败', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  /**
   * 内部文件校验方法
   */
  private async validateFileX(
    path: string,
    content: string,
  ): Promise<{
    isValid: boolean;
    errors: string[];
    warnings?: string[];
  }> {
    const errors: string[] = [];
    const warnings: string[] = [];

    try {
      // TSX 文件特殊校验
      if (path.endsWith('.tsx')) {
        const { TSXComplianceChecker } = await import('../validation/TSXComplianceChecker');
        const complianceResult = TSXComplianceChecker.checkTSXCompliance(content, path);

        if (!complianceResult.isCompliant) {
          const errorMessages = complianceResult.issues
            .filter((issue) => issue.type === 'error')
            .map((issue) => `${issue.code}: ${issue.message}`);

          errors.push(...errorMessages);
        }

        const warningMessages = complianceResult.issues
          .filter((issue) => issue.type === 'warning')
          .map((issue) => `${issue.code}: ${issue.message}`);

        warnings.push(...warningMessages);
      }

      // CSS 文件校验
      if (path.endsWith('.css')) {
        // const cssResult = await validateAndUpdateDocumentCss(content, path);
        // if (!cssResult.success) {
        //   errors.push(`CSS校验失败: ${cssResult.error}`);
        // }
      }

      // 基础内容检查
      if (!content || content.trim().length === 0) {
        warnings.push('文件内容为空');
      }

      return {
        isValid: errors.length === 0,
        errors,
        warnings: warnings.length > 0 ? warnings : undefined,
      };
    } catch (error) {
      return {
        isValid: false,
        errors: [`校验过程出错: ${error.message}`],
      };
    }
  }
}
